package com.caigou.service.impl;

import com.alibaba.druid.sql.visitor.functions.If;
import com.caigou.bean.exam.entity.Users;
import com.caigou.bean.exam.entity.WxUser;
import com.caigou.bean.exam.param.RegisterUserParam;
import com.caigou.bean.param.WxAuthParam;
import com.caigou.bean.vo.AuthLoginTokenVO;
import com.caigou.component.RedisComponent;
import com.caigou.enums.Constant;
import com.caigou.enums.FailResultEnum;
import com.caigou.enums.ResponseEnum;
import com.caigou.mapper.exam.UserInfoMapper;
import com.caigou.mapper.exam.UsersMapper;
import com.caigou.mapper.exam.WxUserMapper;
import com.caigou.security.utils.JwtTokenUtils;
import com.caigou.service.AuthService;
import com.caigou.service.IAuthSignInService;
import com.caigou.service.IUsersService;
import com.caigou.util.RSAUtils;
import com.caigou.util.Result;
import com.caigou.util.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Collections;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class AuthSignInServiceImpl implements IAuthSignInService {
    @Resource
    private AuthService authorize;
    @Resource
    private WxUserMapper wxUserMapper;
    @Resource
    private UsersMapper usersMapper;
    @Resource
    private IUsersService usersService;
    @Resource
    private RedisComponent redisUtil;
    @Resource
    private UserInfoMapper userInfoMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result<String> weChatAuthSignIn() {
        AuthRequest service = authorize.getWxAuthSignInService();
        String authorizeUrl = service.authorize(AuthStateUtils.createState());
        return Result.success(authorizeUrl);
    }

    @Override
    public Result<Object> getAuthResponse(AuthCallback callback) {
        AuthRequest service = authorize.getWxAuthSignInService();
        AuthResponse response = service.login(callback);
        log.info("输出微信返回的信息1"+response.getData());
        log.info("输出微信返回的信2"+response.ok());
        log.info("输出微信返回的信息3"+response.getMsg());
        log.info("输出微信返回的信息4"+response.getCode());


        if (response.ok()) {
            AuthUser data = (AuthUser) response.getData();

            //先查询用户信息
            if (data == null) {
                return Result.error(ResponseEnum.NO_AUTHORIZATION);
            }

            WxUser wxUserByUnionId = wxUserMapper.findWxUserByUnionId(data.getToken().getUnionId());
            log.info("根据uninid查询用户信息={}", wxUserByUnionId);
            if (wxUserByUnionId != null) {
                log.info("根据uninid查询用户信息={}", wxUserByUnionId);
                return Result.success(data);
            }
            log.info("新用户  执行添加用户操作");

            //将微信用户信息插入微信用户表中
            WxUser wxUser = new WxUser();
            wxUser.setUnionid(data.getToken().getUnionId());
            wxUser.setNickname(data.getNickname());
            wxUser.setHeadimgurl(data.getAvatar());
            wxUser.setAccessToken(data.getToken().getAccessToken());
            wxUser.setRefreshToken(data.getToken().getRefreshToken());
            log.info("新用户 打印用户信息-{}", wxUser);
            int insertNum = wxUserMapper.insertSelective(wxUser);
            return Result.success(data);

        }

        return Result.success();
    }

    @Override
    public Result<AuthLoginTokenVO> authWxLoginToken(WxAuthParam param) {
        AuthLoginTokenVO tokenVO = new AuthLoginTokenVO();
        WxUser wxUser = wxUserMapper.findWxUserByUnionId(param.getUnionid());
        //
        log.info("根据用户Unionid查询出的微信用户={}", wxUser);
        if (wxUser == null) {
            //未绑定用户信息
            return Result.success(tokenVO);
        }
        if (StringUtils.isEmpty(wxUser.getUserid().trim())) {
            return Result.success(tokenVO);
        }
        Users users = usersMapper.findUserByUserId(wxUser.getUserid());
        log.info("根据用户userid查询出的用户信息={}", users);
        if (users == null) {
            return Result.success(tokenVO);
        }
        if (users.getUserStatus() == 0) {
            return Result.error(ResponseEnum.FORBIDDEN_ACCOUNT);
        }


        String token = JwtTokenUtils.createToken(users.getTel(), users.getUserid(), Collections.singletonList("user_login"), true);
        userInfoMapper.updateUserLoginNum(users.getUserid());

//        String token = JwtTokenUtils.createToken(jwtUser.getUsername(), false);
        // 返回创建成功的token
        // 但是这里创建的token只是单纯的token
        // 按照jwt的规定，最后请求的时候应该是 `Bearer token`

        tokenVO.setPhoneNumber(users.getTel());
        try {
            String encodedData = RSAUtils.publicEncrypt(String.format(Constant.TOKEN_PREFIX_KEY, users.getUserid(), UUIDUtil.getUUID()), RSAUtils.getPublicKey(JwtTokenUtils.PUBLIC_KYE));  //传入明文和公钥加密,得到密文
            if (!StringUtils.isEmpty(token)) {
                stringRedisTemplate.opsForValue().set(encodedData, JwtTokenUtils.TOKEN_PREFIX + token,JwtTokenUtils.TOKEN_LIFE_TIME, TimeUnit.HOURS);
            }
            tokenVO.setToken(encodedData);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return Result.success(tokenVO);
    }

    @Override
    public Result<AuthLoginTokenVO> bindingWxUserInfo(WxAuthParam param) {

        log.info("输出用户传入参数={}",param);

        //判断用户短信验证是否正确
        String redisSmsKey = Constant.SMS_PRE_KEY + param.getPhoneNumber();
        String redisSmsCode = redisUtil.get(redisSmsKey);
        if (redisSmsCode == null || !redisSmsCode.equals(param.getMsgCode())) {
            return Result.error(FailResultEnum.SMS_CODE_ERROR);
        }

        log.info("用户开始进行微信绑定,输入参数={}", param);
        AuthLoginTokenVO tokenVO = new AuthLoginTokenVO();
        //验证手机号是否注册过
        Users user = usersMapper.findUserByTel(param.getPhoneNumber());

        if (user != null) {
            log.info("查询出用户信息,={}", user.getUserid());
            //先查询用户是否已经绑定微信
            WxUser wxUserDB = wxUserMapper.findWxUserByUserId(user.getUserid());
            log.info("用户微信用户表中查询结果,={}", wxUserDB);
            if (wxUserDB != null) {
                String token = JwtTokenUtils.createToken(user.getTel(), user.getUserid(), Collections.singletonList("user_login"), true);
                userInfoMapper.updateUserLoginNum(user.getUserid());
                if (StringUtils.isEmpty(tokenVO.getToken())) {
                    try {
                        String encodedData = RSAUtils.publicEncrypt(String.format(Constant.TOKEN_PREFIX_KEY, user.getUserid(), UUIDUtil.getUUID()), RSAUtils.getPublicKey(JwtTokenUtils.PUBLIC_KYE));
                        if (!StringUtils.isEmpty(token)) {
                            stringRedisTemplate.opsForValue().set(encodedData, JwtTokenUtils.TOKEN_PREFIX + token,JwtTokenUtils.TOKEN_LIFE_TIME, TimeUnit.HOURS);
                            tokenVO.setToken(encodedData);
                        }
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (InvalidKeySpecException e) {
                        e.printStackTrace();
                    }
                }
            } else {

                log.info("打印出用户传入的Unionid"+param.getUnionid());
                WxUser wxU = wxUserMapper.findWxUserByUnionId(param.getUnionid());
                log.info("打印现有微信用户信息={}",wxU);
                //查询微信是否绑定了用户信息
                if (!StringUtils.isEmpty(wxU.getUserid().trim())) {
                    log.info("查询到用户信息  直接返回");
                    String token = JwtTokenUtils.createToken(user.getTel(), user.getUserid(), Collections.singletonList("user_login"), true);
                    int loginNum = userInfoMapper.updateUserLoginNum(user.getUserid());
                    log.info("修改用户登录日志"+loginNum);
                    if (StringUtils.isEmpty(tokenVO.getToken())) {
                        log.info("token不为空");
                        try {
                            String encodedData = RSAUtils.publicEncrypt(String.format(Constant.TOKEN_PREFIX_KEY, user.getUserid(), UUIDUtil.getUUID()), RSAUtils.getPublicKey(JwtTokenUtils.PUBLIC_KYE));
                            if (!StringUtils.isEmpty(token)) {
                                stringRedisTemplate.opsForValue().set(encodedData, JwtTokenUtils.TOKEN_PREFIX + token,JwtTokenUtils.TOKEN_LIFE_TIME, TimeUnit.HOURS);
                                tokenVO.setToken(encodedData);
                            }
                        } catch (NoSuchAlgorithmException e) {
                            e.printStackTrace();
                        } catch (InvalidKeySpecException e) {
                            e.printStackTrace();
                        }
                    }
                } else {
                    log.info("未查询到用户信息,进行更新绑定操作");
                    //更新操作

                    //绑定微信
                    //进行微信与用户绑定
                    WxUser wxUser = new WxUser();
                    wxUser.setUserid(user.getUserid());
                    wxUser.setUnionid(param.getUnionid());
                    wxUserMapper.updateWxUserInfoByUnionid(wxUser);
                    String token = JwtTokenUtils.createToken(user.getTel(), user.getUserid(), Collections.singletonList("user_login"), true);
                    userInfoMapper.updateUserLoginNum(user.getUserid());
                    int i = usersMapper.updateWxBindingStatus(user.getUserid());
                    if (StringUtils.isEmpty(tokenVO.getToken())) {
                        try {
                            String encodedData = RSAUtils.publicEncrypt(String.format(Constant.TOKEN_PREFIX_KEY, user.getUserid(), UUIDUtil.getUUID()), RSAUtils.getPublicKey(JwtTokenUtils.PUBLIC_KYE));
                            if (!StringUtils.isEmpty(token)) {
                                stringRedisTemplate.opsForValue().set(encodedData, JwtTokenUtils.TOKEN_PREFIX + token,JwtTokenUtils.TOKEN_LIFE_TIME, TimeUnit.HOURS);
                                tokenVO.setToken(encodedData);
                            }
                        } catch (NoSuchAlgorithmException e) {
                            e.printStackTrace();
                        } catch (InvalidKeySpecException e) {
                            e.printStackTrace();
                        }
                    }
                    log.info("微信绑定成功" + i);
                }
            }
            tokenVO.setPhoneNumber(user.getTel());
        } else {

            log.info("用户注册开始");
            //注册用户
            RegisterUserParam registerUserParam = new RegisterUserParam();
            registerUserParam.setMsgCode(param.getMsgCode());
            registerUserParam.setUsername(param.getPhoneNumber());
            registerUserParam.setPassword(param.getPassword());
            Result<Integer> result = usersService.registerUser(registerUserParam);
            if (result.getData() == 1) {
                Users newUser = usersMapper.findUserByTel(param.getPhoneNumber());
                if (newUser != null) {
                    WxUser wxUser = new WxUser();
                    wxUser.setUserid(newUser.getUserid());
                    wxUser.setUnionid(param.getUnionid());
                    WxUser userByUnionId = wxUserMapper.findWxUserByUnionId(param.getUnionid());
                    if (userByUnionId == null) {
                        wxUserMapper.insertSelective(wxUser);
                    } else {
                        wxUserMapper.updateWxUserInfoByUnionid(wxUser);
                    }

                    String token = JwtTokenUtils.createToken(param.getPhoneNumber(), newUser.getUserid(), Collections.singletonList("user_login"), true);
                    userInfoMapper.updateUserLoginNum(newUser.getUserid());
                    tokenVO.setPhoneNumber(newUser.getTel());
                    if (StringUtils.isEmpty(tokenVO.getToken())) {
                        try {
                            String encodedData = RSAUtils.publicEncrypt(String.format(Constant.TOKEN_PREFIX_KEY, newUser.getUserid(), UUIDUtil.getUUID()), RSAUtils.getPublicKey(JwtTokenUtils.PUBLIC_KYE));
                            if (!StringUtils.isEmpty(token)) {
                                stringRedisTemplate.opsForValue().set(encodedData, JwtTokenUtils.TOKEN_PREFIX + token,JwtTokenUtils.TOKEN_LIFE_TIME, TimeUnit.HOURS);
                                tokenVO.setToken(encodedData);
                            }
                        } catch (NoSuchAlgorithmException e) {
                            e.printStackTrace();
                        } catch (InvalidKeySpecException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }


        return Result.success(tokenVO);
    }


}
